1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.util.concurrent;
18
19 import com.google.common.annotations.Beta;
20 import com.google.common.base.Supplier;
21 import com.google.common.base.Throwables;
22
23 import java.util.concurrent.Executor;
24 import java.util.concurrent.TimeUnit;
25 import java.util.concurrent.TimeoutException;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28
29
30
31
32
33
34
35
36
37
38 @Beta
39 public abstract class AbstractExecutionThreadService implements Service {
40 private static final Logger logger = Logger.getLogger(
41 AbstractExecutionThreadService.class.getName());
42
43
44 private final Service delegate = new AbstractService() {
45 @Override protected final void doStart() {
46 Executor executor = MoreExecutors.renamingDecorator(executor(), new Supplier<String>() {
47 @Override public String get() {
48 return serviceName();
49 }
50 });
51 executor.execute(new Runnable() {
52 @Override
53 public void run() {
54 try {
55 startUp();
56 notifyStarted();
57
58 if (isRunning()) {
59 try {
60 AbstractExecutionThreadService.this.run();
61 } catch (Throwable t) {
62 try {
63 shutDown();
64 } catch (Exception ignored) {
65 logger.log(Level.WARNING,
66 "Error while attempting to shut down the service"
67 + " after failure.", ignored);
68 }
69 throw t;
70 }
71 }
72
73 shutDown();
74 notifyStopped();
75 } catch (Throwable t) {
76 notifyFailed(t);
77 throw Throwables.propagate(t);
78 }
79 }
80 });
81 }
82
83 @Override protected void doStop() {
84 triggerShutdown();
85 }
86 };
87
88
89
90
91 protected AbstractExecutionThreadService() {}
92
93
94
95
96
97
98 protected void startUp() throws Exception {}
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 protected abstract void run() throws Exception;
115
116
117
118
119
120
121
122 protected void shutDown() throws Exception {}
123
124
125
126
127
128
129 protected void triggerShutdown() {}
130
131
132
133
134
135
136
137
138
139
140
141
142 protected Executor executor() {
143 return new Executor() {
144 @Override
145 public void execute(Runnable command) {
146 MoreExecutors.newThread(serviceName(), command).start();
147 }
148 };
149 }
150
151 @Override public String toString() {
152 return serviceName() + " [" + state() + "]";
153 }
154
155 @Override public final boolean isRunning() {
156 return delegate.isRunning();
157 }
158
159 @Override public final State state() {
160 return delegate.state();
161 }
162
163
164
165
166 @Override public final void addListener(Listener listener, Executor executor) {
167 delegate.addListener(listener, executor);
168 }
169
170
171
172
173 @Override public final Throwable failureCause() {
174 return delegate.failureCause();
175 }
176
177
178
179
180 @Override public final Service startAsync() {
181 delegate.startAsync();
182 return this;
183 }
184
185
186
187
188 @Override public final Service stopAsync() {
189 delegate.stopAsync();
190 return this;
191 }
192
193
194
195
196 @Override public final void awaitRunning() {
197 delegate.awaitRunning();
198 }
199
200
201
202
203 @Override public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
204 delegate.awaitRunning(timeout, unit);
205 }
206
207
208
209
210 @Override public final void awaitTerminated() {
211 delegate.awaitTerminated();
212 }
213
214
215
216
217 @Override public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
218 delegate.awaitTerminated(timeout, unit);
219 }
220
221
222
223
224
225
226
227
228
229 protected String serviceName() {
230 return getClass().getSimpleName();
231 }
232 }